package com.iflytek.cosmo.ocr.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import com.iflytek.cosmo.ocr.common.config.IflyBarAuthProperties;
import com.iflytek.cosmo.ocr.common.config.LicenseValidateDateConfig;
import com.iflytek.cosmo.ocr.common.constant.CommonConstant;
import com.iflytek.cosmo.ocr.common.constant.LicenseConstant;
import com.iflytek.cosmo.ocr.common.enums.LicenseEnum;
import com.iflytek.cosmo.ocr.common.util.UUIDUtil;
import com.iflytek.cosmo.ocr.dao.IflyBarAuthDao;
import com.iflytek.cosmo.ocr.dao.LicenseDao;
import com.iflytek.cosmo.ocr.dao.MacLicenseDao;
import com.iflytek.cosmo.ocr.model.domain.MessageOutput;
import com.iflytek.cosmo.ocr.model.domain.State;
import com.iflytek.cosmo.ocr.model.entity.LicenseEntity;
import com.iflytek.cosmo.ocr.model.entity.MacLicenseEntity;
import com.iflytek.cosmo.ocr.service.ArgusPostService;
import com.iflytek.cosmo.ocr.service.IflyBarAuthService;
import com.iflytek.cosmo.ocr.support.license.client.ClientLicense;
import com.iflytek.cosmo.ocr.support.license.LicenseManager;
import com.iflytek.cosmo.ocr.support.license.LicenseVersion;
import com.iflytek.cosmo.ocr.support.license.client.v1.ClientLicenseV1;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

@Service
@Transactional(rollbackFor = Exception.class)
public class IflyBarAuthServiceImpl implements IflyBarAuthService {


    /**
     * 日志记录器
     */
    private Logger logger = LoggerFactory.getLogger(IflyBarAuthServiceImpl.class);

    /**
     * 授权码默认的生成数量
     */
    private static final Integer DEFAULT_NUM = 10;

    /**
     * 是否免授权
     */
    @Autowired
    private IflyBarAuthProperties iflyBarAuthProperties;

    /**
     * 授权dao
     */
    @Autowired
    private IflyBarAuthDao iflyBarAuthDao;

    /**
     * mac和授权码关联关系dao
     */
    @Autowired
    private MacLicenseDao macLicenseDao;

    /**
     * 用户dao
     */
    //@Autowired
    //private UserDao userDao;

    /**
     * 授权码表dao
     */
    @Autowired
    private LicenseDao licenseDao;

    @Autowired
    private ArgusPostService argusPostService;

    @Autowired
    private LicenseManager licenseManager;

    @Override
    public boolean verifyAuth(String[] mac, String ip) {
        // mac入参为空,授权不通过
        if (mac.length == 0) {
            logger.info("mac为空,授权不通过");
            return false;
        }

        // 查询mac已绑定授权码 的mac集合
        List<String> authMacList = iflyBarAuthDao.verifyAuth(mac);

        /**
         * 免授权
         */
        if (iflyBarAuthProperties.getAuthEnable() == true) {
            logger.info("进入免授权");
            //String licenseCodeId = licenseDao.getValidLicenseId(LicenseEnum.INIT.getCode()).get(0);
            if (authMacList.size() == 0) {
            	// 默认生成一条授权码
                List<String> list=createLicenseCode(1,LicenseEnum.FREE.getCode());
                String licenseCodeId=list.get(0);
                // mac绑定授权码
                List<MacLicenseEntity> macLicenseList = new ArrayList<MacLicenseEntity>();
                //List<UserEntity> userList = new ArrayList<UserEntity>();
                for (int i = 0; i < mac.length; i++) {
                    // 自动绑定mac和授权码
                    MacLicenseEntity macLicense = new MacLicenseEntity();
                    macLicense.setId(UUIDUtil.getUUID());
                    macLicense.setMac(mac[i].toUpperCase());
                    macLicense.setCodeId(licenseCodeId);
                    macLicenseList.add(macLicense);

                    // 生成用户信息
                    //UserEntity user = new UserEntity();
                   // user.setId(UuidUtil.getUUID());
                    //user.setUsername(mac[i].toUpperCase());
                    //userList.add(user);
                }
                // 批量插入mac和授权码绑定信息
                macLicenseDao.insertBatch(macLicenseList);
                // 批量插入生成用户信息
                //userDao.insertBatch(userList);

                // 向数据分析平台推送(客户端安装数量)
                //argusPostService.argusPost(ArgusConstant.REAL_CLIENT_TYPE, 1, null, macLicenseList.get(0).getMac(), ip);

            } else if (authMacList.size() > 0) {
                // mac绑定授权码
                List<MacLicenseEntity> unmacLicenseList = new ArrayList<MacLicenseEntity>();
                //List<UserEntity> unuserList = new ArrayList<UserEntity>();

                // mac数组转成mac List
                List<String> arrayList = java.util.Arrays.asList(mac);
                List<String> macList = new ArrayList<String>(arrayList);
                Iterator<String> it = macList.iterator();
                while (it.hasNext()) {
                    String macStr = it.next();
                    for (int i = 0; i < authMacList.size(); i++) {
                        if (macStr.equalsIgnoreCase(authMacList.get(i))) {
                            it.remove();
                            break;
                        }
                    }
                }

                if (macList.size() > 0) {
                    for (int i = 0; i < macList.size(); i++) {
                        logger.info("同一台电脑未授权的mac" + macList.get(i));
                        // 默认生成一条授权码
                        List<String> list2=createLicenseCode(1,LicenseEnum.FREE.getCode());
                        /*String licenseCodeId2 = licenseDao.getValidLicenseId(LicenseEnum.INIT.getCode()).get(0);*/
                        String licenseCodeId2=list2.get(0);
                        // 自动绑定mac和授权码
                        MacLicenseEntity macLicense = new MacLicenseEntity();
                        macLicense.setId(UUIDUtil.getUUID());
                        macLicense.setMac(macList.get(i).toUpperCase());
                        macLicense.setCodeId(licenseCodeId2);
                        unmacLicenseList.add(macLicense);

                        // 生成用户信息
                       // UserEntity user = new UserEntity();
                       // user.setId(UuidUtil.getUUID());
                       // user.setUsername(macList.get(i).toUpperCase());
                        //unuserList.add(user);
                    }

                    // 批量插入mac和授权码绑定信息
                    macLicenseDao.insertBatch(unmacLicenseList);
                    // 批量插入生成用户信息
                    //userDao.insertBatch(unuserList);

                    // 向数据分析平台推送(客户端安装数量)
                    //argusPostService.argusPost(ArgusConstant.REAL_CLIENT_TYPE, 1, null, "", ip);

                }
            }
            logger.info("免授权成功");
            return true;
        }

        /**
         * 校验授权成功
         */
        if (authMacList.size() > 0) {
            // mac绑定授权码
            List<MacLicenseEntity> unmacLicenseList = new ArrayList<MacLicenseEntity>();
            //List<UserEntity> unuserList = new ArrayList<UserEntity>();

            // mac数组转成mac List
            List<String> arrayList = java.util.Arrays.asList(mac);
            List<String> macList = new ArrayList<String>(arrayList);
            Iterator<String> it = macList.iterator();
            while (it.hasNext()) {
                String macStr = it.next();
                for (int i = 0; i < authMacList.size(); i++) {
                    if (macStr.equalsIgnoreCase(authMacList.get(i))) {
                        it.remove();
                        break;
                    }
                }
            }
            // 自动为同一台电脑未授权的mac 补全授权
            if (macList.size() > 0) {
            	List<String> list3=createLicenseCode(1,LicenseEnum.FORMAL.getCode());
                String licenseCodeId = list3.get(0);
                for (int i = 0; i < macList.size(); i++) {
                    logger.info("同一台电脑未授权的mac" + macList.get(i));
                    // 默认生成一条授权码
                    // 自动绑定mac和授权码
                    MacLicenseEntity macLicense = new MacLicenseEntity();
                    macLicense.setId(UUIDUtil.getUUID());
                    macLicense.setMac(macList.get(i).toUpperCase());
                    macLicense.setCodeId(licenseCodeId);
                    unmacLicenseList.add(macLicense);

//                    // 生成用户信息
//                    UserEntity user = new UserEntity();
//                    user.setId(UuidUtil.getUUID());
//                    user.setUsername(macList.get(i).toUpperCase());
//                    unuserList.add(user);
                }

                // 批量插入mac和授权码绑定信息
                macLicenseDao.insertBatch(unmacLicenseList);
                // 批量插入生成用户信息
                //userDao.insertBatch(unuserList);
            }

            return true;
        }
        return false;
    }

    @Override
    public MessageOutput<Object> register(String[] mac, String code) {
        /**
         * 确认授权码是否存在
         */
        LicenseEntity license = new LicenseEntity();
        license.setCode(code);
        license = licenseDao.selectOne(license);
        if (license == null) {
            // 如果是RSA加密授权, 无需预先插入数据库, 此时需要将授权码先插入数据库
            ClientLicense decodedLicense = licenseManager.decodeClient(code);
            if (decodedLicense != null) {
                license = new LicenseEntity();
                license.setId(UUIDUtil.getUUID());
                license.setCode(code);
                license.setCreateTime(new Date());
                int version = decodedLicense.getVersion();
                if (LicenseVersion.V1.getCode() == version) {
                    int validityMin = ((ClientLicenseV1) decodedLicense).getValidityMin();
                    license.setExpireTime(DateUtils.addMinutes(new Date(), validityMin));
                }
                licenseDao.insert(license);
            }
            else {
                logger.info(LicenseConstant.LICENSE_CODE_NOT_EXIST);
                return new MessageOutput<Object>(
                        new State(CommonConstant.FAIL_CODE, LicenseConstant.LICENSE_CODE_NOT_EXIST));

            }
        }
        if(LicenseEnum.USED.getCode().equals(license.getState())) {
        	logger.info(LicenseConstant.LICENSE_CODE_IS_USED);
            return new MessageOutput<Object>(new State(CommonConstant.FAIL_CODE, LicenseConstant.LICENSE_CODE_IS_USED));
        }
        
        if(null !=license && null!=license.getExpireTime() && license.getExpireTime().getTime() <new Date().getTime()) {
        	logger.info(LicenseConstant.LICENSE_CODE_IS_OUT_OF_DATE);
            return new MessageOutput<Object>(new State(CommonConstant.FAIL_CODE, LicenseConstant.LICENSE_CODE_IS_OUT_OF_DATE));
        }

        /**
         * 确认授权码是否被注册
         */
        MacLicenseEntity condition = new MacLicenseEntity();
        condition.setCodeId(license.getId());
        List<MacLicenseEntity> ifcMacLicense = macLicenseDao.select(condition);
        if (ifcMacLicense.size() > 0) {
            logger.info(LicenseConstant.LICENSE_CODE_IS_USED);
            return new MessageOutput<Object>(new State(CommonConstant.FAIL_CODE, LicenseConstant.LICENSE_CODE_IS_USED));
        }

        /**
         * 查看mac是否重复授权
         */
        /*List<String> authMacList = iflyBarAuthDao.verifyAuth(mac);
        if (authMacList.size() > 0) {
            logger.info(LicenseConstant.ANTHORIZATION_FAILURES);
            return new MessageOutput<Object>(new State(CommonConstant.FAIL_CODE, LicenseConstant.LICENSE_MAC_IS_USED));
        }*/
        
        /**
         * 删除过期的授权
         */
        iflyBarAuthDao.deleteVerifyAuthOutOfDate(mac);
        
        
        // 注册授权信息list
        List<MacLicenseEntity> macLicenseList = new ArrayList<MacLicenseEntity>();

        // 用户信息list
        //List<UserEntity> userList = new ArrayList<UserEntity>();

        // 生成授权注册信息和用户信息
        for (int i = 0; i < mac.length; i++) {
            // 自动绑定mac和授权码
            MacLicenseEntity macLicense = new MacLicenseEntity();
            macLicense.setId(UUIDUtil.getUUID());
            macLicense.setMac(mac[i].toUpperCase());
            macLicense.setCodeId(license.getId());
            macLicense.setCreateTime(new Date());
            macLicenseList.add(macLicense);

//            // 生成用户信息
//            UserEntity user = new UserEntity();
//            user.setId(UuidUtil.getUUID());
//            user.setUsername(mac[i].toUpperCase());
//            userList.add(user);
        }

        // 批量插入mac和授权码绑定信息
        int macLicenseCount = macLicenseDao.insertBatch(macLicenseList);
        // 批量插入生成用户信息
//        int userCount = userDao.insertBatch(userList);

//        if (macLicenseCount == 0 || userCount == 0) {
        if (macLicenseCount == 0) {
            logger.info(LicenseConstant.ANTHORIZATION_FAILURES);
            return new MessageOutput<Object>(
                    new State(CommonConstant.FAIL_CODE, LicenseConstant.ANTHORIZATION_FAILURES));
        }
        
        //更新授权信息 正式使用 只更新正式使用的
        String type=LicenseEnum.FORMAL.getCode();
        Date now=new Date();
        Example example = new Example(LicenseEntity.class);
        example.createCriteria().andEqualTo("id",license.getId());
        LicenseEntity newLicenseEntity=new LicenseEntity();
        newLicenseEntity.setId(license.getId());
        newLicenseEntity.setType(type);
        newLicenseEntity.setActiveTime(now);
        // newLicenseEntity.setExpireTime(this.calcute(now,type));
        newLicenseEntity.setState(LicenseEnum.USED.getCode());
        this.licenseDao.updateByExampleSelective(newLicenseEntity, example);
        return new MessageOutput<Object>(new State(CommonConstant.SUCCESS_CODE, LicenseConstant.ANTHORIZATION_SUCCESS));
    }

    @Override
    public List<String> createLicenseCode(Integer num) {
        if (num == null || num == 0) {
            num = DEFAULT_NUM;
        }
        List<LicenseEntity> list = new ArrayList<LicenseEntity>();
        List<String> licenseCodeList = new ArrayList<String>();
        for (int i = 0; i < num; i++) {
            LicenseEntity license = new LicenseEntity();
            license.setId(UUIDUtil.getUUID());
            license.setCode(UUID.randomUUID().toString().toUpperCase());
            licenseCodeList.add(license.getCode());
            list.add(license);
        }
        // 批量插入授权码
        licenseDao.insertBatch(list);

        return licenseCodeList;
    }

    @Override
    public List<String> getValidLicenseCode() {
    	String code=LicenseEnum.INIT.getCode();
        return licenseDao.getValidLicenseCode(code);
    }
    
    @Autowired
    private LicenseValidateDateConfig licenseValidateDateConfig;
    @Override
    public List<String> createLicenseCode(Integer num, String type) {
    	LicenseEnum licenseEnum=LicenseEnum.getByCode(type);
    	if(null == licenseEnum) {
    		logger.error("type不正确,授权码类型 试用：trial 正式：formal 免授权:free");
    		return null;
    	}
        if (num == null || num == 0) {
            num = DEFAULT_NUM;
        }
        List<LicenseEntity> list = new ArrayList<LicenseEntity>();
        List<String> licenseCodeList = new ArrayList<String>();
        try {
        	Date now=new Date();
			for (int i = 0; i < num; i++) {
			    LicenseEntity license = new LicenseEntity();
			    license.setId(UUIDUtil.getUUID());
			    license.setCode(UUID.randomUUID().toString().toUpperCase());
			    license.setActiveTime(now);
			    Date expireDate=this.calcute(now,type);
			    license.setExpireTime(expireDate);
			    license.setState(LicenseEnum.USED.getCode());
			    license.setType(type);
			    licenseCodeList.add(license.getId());
			    list.add(license);
			}
			// 批量插入授权码
			licenseDao.insertBatchOther(list);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

        return licenseCodeList;
    }
    
    private Date calcute(Date now,String type) {
    	int amount=licenseValidateDateConfig.getValidateDateMap().get(type);
    	Date deadline =null;
    	switch (type) {
		case "trial":
			deadline = DateUtils.addDays(now, amount);
			break;
        case "formal":
        	deadline = DateUtils.addMonths(now, amount);
			break;
        case "free":
        	deadline = DateUtils.addYears(now, amount);
			break;
		default:
			break;
		}
        return deadline;
    }
}
